package ru.magicreader;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

import ru.magicreader.model.Feed;
import ru.magicreader.model.User;

import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.fetcher.FeedFetcher;
import com.sun.syndication.fetcher.FetcherException;
import com.sun.syndication.fetcher.impl.FeedFetcherCache;
import com.sun.syndication.fetcher.impl.HashMapFeedInfoCache;
import com.sun.syndication.fetcher.impl.HttpURLFeedFetcher;
import com.sun.syndication.io.FeedException;

/**
 * This servlet takes data from FormMain and generates input for tagcloud widget
 */
public class FeedServlet extends HttpServlet {
	private static final String INPUT_SESSION_ATTRIBUTE = "input";
	public static final String USER_SESSION_ATTRIBUTE = "user";

	private static final int DEFAULT_MAX_FEED_ENTRIES = 5;
	
	private static final long serialVersionUID = 1L;
	private static FeedFetcherCache feedInfoCache = HashMapFeedInfoCache.getInstance();
	private FeedFetcher fetcher = new HttpURLFeedFetcher(feedInfoCache);
	private XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat());
	private PersistenceManager persistenceManager;
       
    public FeedServlet() {
        super();
    }

    @Override
	public void init(ServletConfig config) throws ServletException {
		persistenceManager = PersistenceFacade.getInstance().getPersistenceManager();
	}

	@Override
	public void destroy() {
		persistenceManager.close();
	}

	/**
	 * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String actionParam = (String)request.getParameter("action");
		
		try {
			if(actionParam != null && actionParam.equalsIgnoreCase("login")) { //login request
				FormLogin formLogin = (FormLogin)request.getSession().getAttribute("formLogin");
				User user = retrieveUser(formLogin);
				request.getSession().setAttribute(USER_SESSION_ATTRIBUTE, user);
				
				Document tagcloudInput = generateInput(user.getFeeds());
				request.getSession().setAttribute(INPUT_SESSION_ATTRIBUTE, tagcloudInput);
				response.sendRedirect("main.jsp");
			}
			if(actionParam != null && actionParam.equalsIgnoreCase("newFeed")) { //newFeed request
				//first get the user
				User user = (User)request.getSession().getAttribute(USER_SESSION_ATTRIBUTE);
				if(user == null) { //not logged in or session expired
					response.sendRedirect("login.jsp");
					return;
				}
				
				//add new feed to user feeds
				FormMain formBean = (FormMain)request.getSession().getAttribute("bean");
				List<Feed> feeds = user.getFeeds();
				feeds.add(new Feed(formBean.getFeedUrl()));
				
				//generate input and redirect
				Document tagcloudInput = generateInput(feeds);
				request.getSession().setAttribute(INPUT_SESSION_ATTRIBUTE, tagcloudInput);
				response.sendRedirect("main.jsp");
			}
			else { //request for input
				Document input = (Document)request.getSession().getAttribute(INPUT_SESSION_ATTRIBUTE);
				if(input != null) {
					PrintWriter out = response.getWriter();
					xmlOutputter.output(input, out);
					out.flush();
				}
			}
		}
		catch(MalformedURLException e) {
			//TODO: report "Invalid URL"
			throw new ServletException(e);
		}
		catch(FetcherException e) {
			//TODO: report "Unable to fetch feed"
			throw new ServletException(e);
		}
		catch(FeedException e) {
			//TODO: report "Problem with feed"
			throw new ServletException(e);
		}
	}


	private User retrieveUser(FormLogin formLogin) {
		User ret = null;
		try {
			ret = (User)persistenceManager.getObjectById(formLogin.getLogin());
		}
		catch(Throwable e) {}
		if(ret != null) return ret;
		
		return persistenceManager.makePersistent(new User(formLogin.getLogin()));
	}

	@SuppressWarnings("unchecked")
	private Document generateInput(List<Feed> feeds) throws IllegalArgumentException, MalformedURLException, IOException, FeedException, FetcherException {
		Document ret = new Document();
		Element root = new Element("tags");
		ret.setRootElement(root);
		
		for(Feed feed : feeds) {
			SyndFeed syndFeed = fetcher.retrieveFeed(new URL(feed.getUrl()));
			
			List<SyndEntry> feedEntries = syndFeed.getEntries();
			int count = 0;
			for(SyndEntry entry : feedEntries) {
				Element a = new Element("a");
				a.setAttribute("href", entry.getLink());
				
				int fontSize = 5;
				if(count == 0) { //first element
					fontSize = 12;
				}
				else if(count > 0 && count < 4) { //next 3 elements
					fontSize = 9;
				}
				a.setAttribute("style", "font-size: " + fontSize + "pt;");
				
				a.setAttribute("color", "0x282828");
				a.setAttribute("hicolor", "0xE44203");
				a.setAttribute("target", "_blank");
				
				a.setText(entry.getTitle());
				
				root.addContent(a);
				
				if(count++ == DEFAULT_MAX_FEED_ENTRIES) break;
			}
		}
		
		return ret;
	}
	
}
